home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / unix / expnntp / dirutil.c next >
Encoding:
C/C++ Source or Header  |  1994-06-24  |  20.4 KB  |  861 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  *
  8.  * Added path filter functions and applied to dodir
  9.  * also used by ftpcli.c, added current directory
  10.  * storage capability (11/92 WA3DSP)
  11.  * Bugfixes in the above by WG7J, WA7TAS
  12.  */
  13.   
  14. #ifndef UNIX
  15. #include <dir.h>
  16. #include <dos.h>
  17. #else
  18. #include <sys/stat.h>
  19. /* There are at least FOUR variants of statfs()... we handle SCO and Linux */
  20. #ifdef M_UNIX
  21. #include <sys/statfs.h>
  22. #define f_bavail f_bfree
  23. #else
  24. #include <sys/vfs.h>
  25. #endif /* M_UNIX */
  26. #endif /* UNIX */
  27. #include <ctype.h>
  28. #ifndef UNIX
  29. #include <io.h>
  30. #endif
  31. #include "global.h"
  32. #include "proc.h"
  33. #include "session.h"
  34. #include "dirutil.h"
  35. #include "commands.h"
  36.   
  37. #ifdef CALLSERVER
  38. #include <string.h>
  39. #include <alloc.h>
  40. extern char *CDROM; /* buckbook.c: defines CDROM drive letter e.g. "s:"  */
  41. #endif
  42.   
  43. struct dirsort {
  44.     struct dirsort *next;
  45.     struct ffblk de;
  46. };
  47. #define NULLSORT (struct dirsort *)0
  48.   
  49. static void commas __ARGS((char *dest));
  50. static int fncmp __ARGS((char *a, char *b));
  51. static void format_fname_full __ARGS((FILE *file,struct ffblk *sbuf,int full,
  52. int n));
  53. static void free_clist __ARGS((struct dirsort *this));
  54.   
  55. #ifdef  notdef
  56. static int getdir_nosort __ARGS((char *path,int full,FILE *file));
  57. #endif
  58. static void print_free_space __ARGS((char *path,FILE *file,int n));
  59.   
  60. extern void crunch __ARGS((char *buf,char *path));
  61.   
  62. #define REGFILE (FA_DIREC)
  63.   
  64. #define insert_ptr(list,new)    (new->next = list,list = new)
  65.   
  66.   
  67. /* Create a directory listing in a temp file and return the resulting file
  68.  * descriptor. If full == 1, give a full listing; else return just a list
  69.  * of names.
  70.  */
  71. FILE *
  72. dir(path,full)
  73. char *path;
  74. int full;
  75. {
  76.     FILE *fp;
  77.   
  78.     if((fp = tmpfile()) != NULLFILE){
  79.         getdir(path,full,fp);
  80.         rewind(fp);
  81.     }
  82.     return fp;
  83. }
  84.   
  85. /* find the first or next file and lowercase it. */
  86. int
  87. nextname(command, name, sbuf)
  88. int command;
  89. char *name;
  90. struct ffblk *sbuf;
  91. {
  92.     int found;
  93.   
  94.     switch(command){
  95.         case 0:
  96.             found = findfirst(name,sbuf,REGFILE);
  97.             break;
  98.         default:
  99.             found = findnext(sbuf);
  100.     }
  101.     found = found == 0;
  102. #ifndef UNIX
  103.     if(found)
  104.         strlwr(sbuf->ff_name);
  105. #endif
  106.   
  107.     return found;
  108. }
  109.   
  110. /* wildcard filename lookup */
  111. int
  112. filedir(name,times,ret_str)
  113. char *name;
  114. int times;
  115. char *ret_str;
  116. {
  117.     static struct ffblk sbuf;
  118.     int rval;
  119.   
  120.     switch(times){
  121.         case 0:
  122.             rval = findfirst(name,&sbuf,REGFILE);
  123.             break;
  124.         default:
  125.             rval = findnext(&sbuf);
  126.             break;
  127.     }
  128.     if(rval == -1){
  129.         ret_str[0] = '\0';
  130.     } else {
  131.         /* Copy result to output */
  132.         strcpy(ret_str, sbuf.ff_name);
  133.     }
  134.     return rval;
  135. }
  136. /* do a directory list to the stream
  137.  * full = 0 -> short form, 1 is long
  138. */
  139. int
  140. getdir(path,full,file)
  141. char *path;
  142. int full;
  143. FILE *file;
  144. {
  145.     struct ffblk *sbuf;
  146.     int command = 0;
  147.     int n = 0;
  148.     struct dirsort *head, *here, *new;
  149.   
  150.     sbuf = mallocw(sizeof *sbuf);
  151.     path = wildcardize(path);
  152.   
  153.     head = NULLSORT;        /* No head of chain yet... */
  154.     for(;;){
  155.         if (!nextname(command, path, sbuf))
  156.             break;
  157.         command = 1;    /* Got first one already... */
  158.         if (sbuf->ff_name[0] == '.')     /* drop "." and ".." */
  159. #ifdef UNIX
  160.             if (sbuf->ff_name[1] == '\0' || (sbuf->ff_name[1] == '.' &&
  161.                 sbuf->ff_name[2] == '\0'))
  162. #endif
  163.                 continue;
  164.   
  165.         new = (struct dirsort *) mallocw(sizeof(struct dirsort));
  166.         memcpy(&new->de, sbuf, sizeof *sbuf); /* Copy contents of directory entry struct */
  167.   
  168.         /* insert it into the list */
  169.         if (!head || fncmp(new->de.ff_name, head->de.ff_name) < 0) {
  170.             insert_ptr(head, new);
  171.         } else {
  172.             register struct dirsort *this;
  173.             for (this = head;
  174.                 this->next != NULLSORT;
  175.                 this = this->next)
  176.                 if (fncmp(new->de.ff_name, this->next->de.ff_name) < 0)
  177.                     break;
  178.             insert_ptr(this->next, new);
  179.         }
  180.     } /* infinite FOR loop */
  181.   
  182.     for (here = head; here; here = here->next)
  183.         format_fname_full(file,&here->de,full,++n);
  184.   
  185.     /* Give back all the memory we temporarily needed... */
  186.     free_clist(head);
  187.     free(sbuf);
  188.   
  189.     if(full)
  190.         print_free_space(path, file, n);
  191.   
  192.     return 0;
  193. }
  194.   
  195. static int
  196. fncmp(a,b)
  197. register char *a, *b;
  198. {
  199.     int i;
  200.   
  201.     for(;;){
  202.         if (*a == '.')
  203.             return -1;
  204.         if (*b == '.')
  205.             return 1;
  206.         if ((i = *a - *b++) != 0)
  207.             return i;
  208.         if (!*a++)
  209.             return -1;
  210.     }
  211. }
  212.   
  213.   
  214. #if defined DIRSESSION || defined FTPSESSION
  215.   
  216. extern int morecmd();
  217. /* List directory to console */
  218. int
  219. dircmd(argc,argv,p)
  220. int argc;
  221. char *argv[];
  222. void *p;
  223. {
  224.     char *path;
  225.     FILE *fp;
  226.     char **margv;
  227.     char tmpname[80];
  228.   
  229.     path=strdup(make_dir_path(argc,argv[1],Command->curdirs->dir));
  230.     margv = (char **)callocw(2,sizeof(char *));
  231.     tmpnam(tmpname);
  232.     fp = fopen(tmpname,WRITE_TEXT);
  233.     getdir(path,1,fp);
  234.     free(path);
  235.     fclose(fp);
  236.     margv[1] = strdup(tmpname);
  237.     morecmd(2,margv,p);
  238.     free(margv[1]);
  239.     free(margv);
  240.     unlink(tmpname);
  241.     return 0;
  242. }
  243. #endif  /* DIRSESSION || FTPSESSION */
  244.   
  245. #ifdef DIRSESSION
  246.   
  247. int
  248. dodir(argc,argv,p)
  249. int argc;
  250. char *argv[];
  251. void *p;
  252. {
  253.     char **pargv;
  254.     int i;
  255.   
  256.     if(Curproc->input == Command->input) {
  257.         /* Make private copy of argv and args,
  258.          * spawn off subprocess and return.
  259.          */
  260.         pargv = (char **)callocw(argc,sizeof(char *));
  261.         for(i=0;i<argc;i++)
  262.             pargv[i] = strdup(argv[i]);
  263.         newproc("dir",512,(void (*)__ARGS((int,void*,void*)))dircmd,argc,(void *)pargv,p,1);
  264.     } else
  265.         dircmd(argc,argv,p);
  266.     return 0;
  267. }
  268.   
  269. #endif /* DIRSESSION */
  270.   
  271. /*
  272.  * Return a string with commas every 3 positions.
  273.  * the original string is replace with the string with commas.
  274.  *
  275.  * The caller must be sure that there is enough room for the resultant
  276.  * string.
  277.  *
  278.  *
  279.  * k3mc 4 Dec 87
  280.  */
  281. static void
  282. commas(dest)
  283. char *dest;
  284. {
  285.     char *src, *core;       /* Place holder for malloc */
  286.     unsigned cc;            /* The comma counter */
  287.     unsigned len;
  288.   
  289.     len = strlen(dest);
  290.     /* Make a copy, so we can muck around */
  291.     core = src = strdup(dest);
  292.   
  293.     cc = (len-1)%3 + 1;     /* Tells us when to insert a comma */
  294.   
  295.     while(*src != '\0'){
  296.         *dest++ = *src++;
  297.         if( ((--cc) == 0) && *src ){
  298.             *dest++ = ','; cc = 3;
  299.         }
  300.     }
  301.     free(core);
  302.     *dest = '\0';
  303. }
  304.   
  305. /* fix up the filename so that it contains the proper wildcard set */
  306. char *
  307. wildcardize(path)
  308. char *path;
  309. {
  310. #ifdef UNIX
  311.     static
  312. #endif
  313.     struct ffblk sbuf;
  314. #ifdef UNIX
  315.     static char ourpath[1024];
  316. #else
  317.     static char ourpath[64];
  318. #endif
  319.   
  320.     /* Root directory is a special case */
  321.     if(path == NULLCHAR ||
  322.         *path == '\0' ||
  323.         strcmp(path,"\\") == 0 ||
  324.     strcmp(path,"/") == 0) {
  325. #ifdef UNIX
  326.         strcpy(ourpath,"/*");
  327. #else
  328.         strcpy(ourpath,"/*.*");
  329. #endif
  330.         return ourpath;
  331.     }
  332.   
  333. #ifdef CALLSERVER
  334.     if  (CDROM != NULLCHAR && strcmp(path, CDROM) == 0)  {
  335. #ifdef UNIX
  336.         sprintf(ourpath, "%s/*", CDROM);
  337. #else
  338.         sprintf(ourpath, "%s/*.*", CDROM);
  339. #endif
  340.         return ourpath;
  341.     }
  342. #endif
  343.   
  344.     /* if they gave the name of a subdirectory, append \*.* to it */
  345.     if (nextname(0, path, &sbuf) &&
  346.         (sbuf.ff_attrib & FA_DIREC) &&
  347.     !nextname(1, path, &sbuf)) {
  348.   
  349.         /* if there isn't enough room, give up -- it's invalid anyway */
  350. #ifdef UNIX
  351.         if (strlen(path) + 2 > sizeof(ourpath) - 1) return path;
  352. #else
  353.         if (strlen(path) + 4 > sizeof(ourpath) - 1) return path;
  354. #endif
  355.         strcpy(ourpath, path);
  356. #ifdef UNIX
  357.         strcat(ourpath, "/*");
  358. #else
  359.         strcat(ourpath, "/*.*");
  360. #endif
  361.         return ourpath;
  362.     }
  363. #ifdef UNIX
  364.     findlast(&sbuf);
  365. #endif
  366.   
  367.     return path;
  368. }
  369.   
  370. static void
  371. format_fname_full(file, sbuf, full, n)
  372. FILE *file;
  373. struct ffblk *sbuf;
  374. int full, n;
  375. {
  376. #ifdef UNIX
  377.     static char line_buf[1025];
  378.     static char cbuf[1025];
  379. #else
  380.     char line_buf[50];              /* for long dirlist */
  381.     char cbuf[20];                  /* for making line_buf */
  382. #endif
  383.   
  384.     strcpy(cbuf,sbuf->ff_name);
  385.     if(sbuf->ff_attrib & FA_DIREC) strcat(cbuf, "/");
  386.     if (full) {
  387.         /* Long form, give other info too */
  388.         sprintf(line_buf,"%-13s",cbuf);
  389.         if(sbuf->ff_attrib & FA_DIREC)
  390.             strcat(line_buf,"           ");/* 11 spaces */
  391.         else {
  392.             sprintf(cbuf,"%ld",sbuf->ff_fsize);
  393.             commas(cbuf);
  394.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  395.         }
  396.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  397. #ifdef UNIX
  398.         sbuf->ff_ftime.tm_hour, sbuf->ff_ftime.tm_min,
  399.         sbuf->ff_ftime.tm_mon + 1, sbuf->ff_ftime.tm_mday,
  400.         sbuf->ff_ftime.tm_year,
  401. #else
  402.         (sbuf->ff_ftime >> 11) & 0x1f,        /* hour */
  403.         (sbuf->ff_ftime >> 5) & 0x3f, /* minute */
  404.         (sbuf->ff_fdate >> 5) & 0xf,  /* month */
  405.         (sbuf->ff_fdate ) & 0x1f,             /* day */
  406.         (sbuf->ff_fdate >> 9) + 80,   /* year */
  407. #endif
  408.         (n & 1) ? "   " : "\n");
  409.         fputs(line_buf,file);
  410.     } else {
  411.         fputs(cbuf,file);
  412.         fputs("\n",file);
  413.     }
  414. }
  415. /* Provide additional information only on DIR */
  416. static void
  417. print_free_space(path, file, n)
  418. char *path;
  419. FILE *file;
  420. int n;
  421. {
  422.     unsigned long free_bytes, total_bytes;
  423.     char s_free[25], s_total[25]; /* Changed to accomodate big disks - WA7TAS */
  424.     char cbuf[20];
  425. #ifdef UNIX
  426.     char *pbuf;
  427.     struct statfs vfsb;
  428.     char *cp;
  429.   
  430.     pbuf = mallocw(1024);
  431.     strcpy(pbuf, path);
  432.     if ((cp = strrchr(pbuf, '/')) == 0)
  433.         strcat(pbuf, "/.");
  434.     else
  435.     {
  436.         *++cp = '.';
  437.         *++cp = '\0';
  438.     }
  439. #ifdef M_UNIX
  440.     statfs(pbuf, &vfsb, sizeof vfsb, 0);
  441. #else
  442.     statfs(pbuf, &vfsb);
  443. #endif
  444.     free_bytes = vfsb.f_bsize * vfsb.f_bavail;
  445.     total_bytes = vfsb.f_bsize * vfsb.f_blocks;
  446. #else /* UNIX */
  447.     struct dfree dtable;
  448.     unsigned long bpcl;
  449.     char resolved[80];      /* may need as little as 67 */
  450.     union REGS regs;
  451.     struct SREGS sregs;
  452.     int drive;
  453.     char drivex[3];
  454.   
  455.     if(_osmajor>=3) {
  456.         /* do an undocumented call to find which drive this name resolves to */
  457.         /*  this call does *NOT* work in dos <3.0 */
  458.         regs.x.si = FP_OFF(path);
  459.         sregs.ds = FP_SEG(path);
  460.         regs.x.di = FP_OFF(resolved);
  461.         sregs.es = FP_SEG(resolved);
  462.         regs.h.ah = 0x60;
  463.         intdosx(®s,®s,&sregs);
  464.         drive = resolved[0] - '@';
  465.     }
  466.     else {
  467.         /* use a method that works for dos < 3.0 */
  468.         drivex[0]=0;
  469.         for(drive=0;drive<strlen(path);drive++)
  470.             path[drive]=toupper(path[drive]);
  471.         fnsplit(path,drivex,NULL,NULL,NULL);
  472.         if(drivex[0])
  473.             drive = drivex[0] - '@';
  474.         else
  475.             drive = 0;
  476.     }
  477.   
  478.     /* Find disk free space */
  479.     getdfree(drive,&dtable);
  480.   
  481.  /* Changed to accomodate big disks - WA7TAS */
  482.     bpcl = (unsigned long)dtable.df_bsec * (unsigned long)dtable.df_sclus;
  483.     free_bytes  = (unsigned long)dtable.df_avail * bpcl;
  484.     total_bytes = (unsigned long)dtable.df_total * bpcl;
  485. #endif /* UNIX */
  486.   
  487.     if(n & 1)
  488.         fputs("\n",file);
  489.   
  490.     sprintf(s_free,"%ld",free_bytes);
  491.     commas(s_free);
  492.     sprintf(s_total,"%ld",total_bytes);
  493.     commas(s_total);
  494.   
  495.     if(n)
  496.         sprintf(cbuf,"%d",n);
  497.     else
  498.         strcpy(cbuf,"No");
  499.   
  500.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  501.     cbuf,(n==1? "":"s"),s_free,s_total);
  502. }
  503. static void
  504. free_clist(this)
  505. struct dirsort *this;
  506. {
  507.     struct dirsort *next;
  508.   
  509.     while (this != NULLSORT) {
  510.         next = this->next;
  511.         free(this);
  512.         this = next;
  513.     }
  514. }
  515. #ifdef  notdef
  516. static int
  517. getdir_nosort(path,full,file)
  518. char *path;
  519. int full;
  520. FILE *file;
  521. {
  522.     struct ffblk sbuf;
  523.     int command;
  524.     int n = 0;      /* Number of directory entries */
  525.   
  526. /*      path = wildcardize(path); */
  527.     command = 0;
  528.     while(nextname(command, path, &sbuf)){
  529.         command = 1;    /* Got first one already... */
  530.         if (sbuf.ff_name[0] == '.')     /* drop "." and ".." */
  531.             continue;
  532.         format_fname_full(file, &sbuf, full, ++n);
  533.     }
  534.     if(full)
  535.         print_free_space(path, file, n);
  536.     return 0;
  537. }
  538. #endif
  539.   
  540. /* Translate those %$#@!! backslashes to proper form */
  541. void
  542. undosify(s)
  543. char *s;
  544. {
  545.     while(*s != '\0'){
  546.         if(*s == '\\')
  547.             *s = '/';
  548.         s++;
  549.     }
  550. }
  551.   
  552. char *
  553. make_dir_path(int count,char * arg,char * curdir)
  554. {
  555.     char path[128], *q;
  556.   
  557.     undosify(arg);
  558.     undosify(curdir);
  559.     if (count>=2) {
  560.         q=arg;
  561.         q+=strlen(arg)-1;
  562.         if (*q=='/' || *q==':') {
  563.             strcpy(path,arg);
  564. #ifdef UNIX
  565.             strcat(path,"*");
  566. #else
  567.             strcat(path,"*.*");
  568. #endif
  569.         } else
  570.             strcpy(path,arg);
  571.     } else {
  572. #ifdef UNIX
  573.         strcpy(path,"*");
  574. #else
  575.         strcpy(path,"*.*");
  576. #endif
  577.     }
  578.     return (make_fname(curdir,path));
  579. }
  580.   
  581. char*
  582. make_fname(char * curdir, char * fname)
  583. {
  584.     char *p;
  585.     static char new_name[128];
  586.   
  587.     strcpy(new_name,curdir);
  588.     undosify(fname);
  589. #ifdef UNIX
  590.     if (fname[0]=='/') {
  591. #else
  592.         if (fname[0]=='/' || (strchr(fname,':') != NULLCHAR) ) {
  593. #endif
  594.             return fname;
  595.         } else {
  596.             p=new_name;
  597.             p+=strlen(p)-1;
  598.             if (*p=='/')
  599.                 *p='\0';
  600.             crunch(new_name,fname);
  601.             return new_name;
  602.         }
  603.     }
  604.   
  605. /* Check Drive/Directory for validity - 1=OK, 0=NOGOOD */
  606.   
  607.     int
  608.     dir_ok(char * newpath,struct cur_dirs * dirs)
  609.     {
  610.         char *a, curpath[128];
  611.         char buf[128],fullpath[128];
  612.         int result;
  613. #ifndef UNIX
  614.         int drive=dirs->drv;
  615. #endif
  616.   
  617.         undosify(newpath);
  618. #ifndef UNIX
  619.         a=newpath;
  620.         if ((*(a+1)==':') && (isalpha(*a))){
  621.             drive=toupper(*a)-'@';
  622.             strcpy(buf,a+2);
  623.             if (dirs->curdir[drive]==NULLCHAR) {
  624.                 if(!getcurdir(drive,curpath)) {
  625.                     undosify(curpath);
  626.                     sprintf(fullpath,"%c:/%s",drive+'@',curpath);
  627.                     dirs->curdir[drive]=strdup(fullpath);
  628.                     dirs->drv=drive;
  629.                     dirs->dir=dirs->curdir[drive];
  630.                 }
  631.             }
  632.         } else {
  633.             strcpy(buf,newpath);
  634.         }
  635.   
  636.         if((a=dirs->curdir[drive])!=NULLCHAR) {
  637.             if ((*(a+1)==':') && (isalpha(*a))){
  638.                 if (*(a+2)=='/')
  639.                     strcpy(curpath,a+3);
  640.                 else
  641.                     strcpy(curpath,a+2);
  642.             } else {
  643.                 strcpy(curpath,a);
  644.             }
  645.         } else {
  646.             strcpy(curpath,"");
  647.         }
  648. #endif
  649.   
  650.         if (*buf!='/') {
  651.             crunch(curpath,buf);
  652.         } else {
  653.             strcpy(curpath,buf+1);
  654.         }
  655.         a=curpath;
  656. #ifdef UNIX
  657.         sprintf(fullpath,"%s%s",(*a!='/' ? "/" : ""),curpath);
  658. #else
  659.         sprintf(fullpath,"%c:%s%s",drive+'@',(*a!='/' ? "/" : ""),curpath);
  660. #endif
  661.   
  662.         if((result=access(fullpath,0)+1)==1) {
  663. #ifdef UNIX
  664.             free(dirs->dir);
  665.             dirs->dir = strdup(fullpath);
  666. #else
  667.             if(dirs->curdir[drive])
  668.                 free(dirs->curdir[drive]);
  669.             dirs->curdir[drive]=strdup(fullpath);
  670.             dirs->drv=drive;
  671.             dirs->dir=dirs->curdir[drive];
  672. #endif
  673.         }
  674.         return result;
  675.     }
  676.   
  677.     char *
  678.     init_dirs(struct cur_dirs * dirs)
  679.     {
  680. #ifdef UNIX
  681.         dirs->dir = getcwd(NULL, 1024);
  682.         return dirs->dir;
  683. #else
  684.         char buf[128],fullpath[128];
  685.         int x,drive;
  686.   
  687.         for(x=0;x<=26;x++)
  688.             dirs->curdir[x]='\0';
  689.   
  690.         drive=getdisk()+1;
  691.         getcurdir(drive,buf);
  692.         undosify(buf);
  693.         sprintf(fullpath,"%c:/%s",drive+'@',buf);
  694.         dirs->curdir[drive]=strdup(fullpath);
  695.         dirs->drv=drive;
  696.         dirs->dir=dirs->curdir[drive];
  697.         return dirs->curdir[drive];
  698. #endif
  699.     }
  700.   
  701.     void
  702.     free_dirs(struct cur_dirs * dirs)
  703.     {
  704. #ifdef UNIX
  705.         free(dirs->dir);
  706. #else
  707.         int x;
  708.   
  709.         for(x=0;x<=26;x++) {
  710.             if (dirs->curdir[x])
  711.                 free(dirs->curdir[x]);
  712.         }
  713. #endif
  714.     }
  715.   
  716. #ifdef  MSDOS
  717. /* Valid characters in a DOS filename matrix */
  718.     static unsigned char doschars[] = {
  719.         0x00, 0x00, 0x00, 0x00, 0xfa, 0x23, 0xff, 0x03,
  720.         0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0x6f,
  721.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  722.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  723.     };
  724.   
  725.     int
  726.     dosfnchr(ch)
  727.     int ch;
  728.     {
  729.         int i, j;
  730.   
  731.         i = (ch & 0xf8) >> 3;
  732.         j = doschars[i] & (1 << (ch & 0x07));
  733.         return j;
  734.     }
  735. #endif
  736.   
  737. #ifdef DOSCMD
  738. /* Standard commands called from main */
  739.     int
  740.     dodelete(argc,argv,p)
  741.     int argc;
  742.     char *argv[];
  743.     void *p;
  744.     {
  745.         int i;
  746.         char fname[128];
  747.   
  748.         for(i=1;i < argc; i++){
  749.             strcpy(fname,make_fname(Command->curdirs->dir,argv[i]));
  750.             if(unlink(fname) == -1){
  751.                 tprintf("Can't delete %s: %s\n",fname,sys_errlist[errno]);
  752.             }
  753.         }
  754.         return 0;
  755.     }
  756.   
  757.     int
  758.     dorename(argc,argv,p)
  759.     int argc;
  760.     char *argv[];
  761.     void *p;
  762.     {
  763.         char fname1[128];
  764.         char fname2[128];
  765.   
  766.         strcpy(fname1,make_fname(Command->curdirs->dir,argv[1]));
  767.         strcpy(fname2,make_fname(Command->curdirs->dir,argv[2]));
  768.         if(rename(fname1,fname2) == -1)
  769.             tprintf("Can't rename: %s\n",sys_errlist[errno]);
  770.         return 0;
  771.     }
  772.   
  773.     int
  774.     docopy(argc,argv,p)
  775.     int argc;
  776.     char *argv[];
  777.     void *p;
  778.     {
  779.         FILE *old, *new;
  780.         int ch;
  781.         unsigned char count;
  782.         char fname[128];
  783.   
  784.         strcpy(fname,make_fname(Command->curdirs->dir,argv[1]));
  785.         if((old = fopen(fname,"rb")) == NULL) {
  786.             tprintf("Can't open %s: %s\n",fname,sys_errlist[errno]);
  787.             return 1;
  788.         }
  789.         strcpy(fname,make_fname(Command->curdirs->dir,argv[2]));
  790.         if((new = fopen(fname,"wb")) == NULL) {
  791.             tprintf("Can't open %s: %s\n",fname,sys_errlist[errno]);
  792.             fclose(old);
  793.             return 1;
  794.         }
  795.     /* Now go copy */
  796.         count = 0;
  797.         while((ch = fgetc(old)) != EOF) {
  798.             fputc(ch,new);
  799.             if(!(++count))      /* be polite to other users */
  800.                 pwait(NULL);
  801.         }
  802.         fclose(old);
  803.         fclose(new);
  804.         return 0;
  805.     }
  806.   
  807. /* Change working directory */
  808.     int
  809.     docd(argc,argv,p)
  810.     int argc;
  811.     char *argv[];
  812.     void *p;
  813.     {
  814.         if(argc > 1){
  815.             if (!dir_ok(argv[1],Command->curdirs)) {
  816.                 tprintf("Invalid Drive/Directory - %s\n",argv[1]);
  817.                 return 1;
  818.             }
  819.         }
  820.         tprintf("Local Directory - %s\n",Command->curdirs->dir);
  821.         return 0;
  822.     }
  823.   
  824. /* Create directory */
  825.     int
  826.     domkd(argc,argv,p)
  827.     int argc;
  828.     char *argv[];
  829.     void *p;
  830.     {
  831.         char path[128];
  832.   
  833.         strcpy(path,make_fname(Command->curdirs->dir,argv[1]));
  834.   
  835. #ifdef UNIX
  836.         if(mkdir(path, 0777) == -1)
  837. #else
  838.             if(mkdir(path) == -1)
  839. #endif
  840.                 tprintf("Can't make %s: %s\n",path,sys_errlist[errno]);
  841.         return 0;
  842.     }
  843.   
  844. /* Remove directory */
  845.     int
  846.     dormd(argc,argv,p)
  847.     int argc;
  848.     char *argv[];
  849.     void *p;
  850.     {
  851.         char path[128];
  852.   
  853.         strcpy(path,make_fname(Command->curdirs->dir,argv[1]));
  854.         if(rmdir(path) == -1)
  855.             tprintf("Can't remove %s: %s\n",path,sys_errlist[errno]);
  856.         return 0;
  857.     }
  858.   
  859. #endif /* DOSCMD */
  860.   
  861.